/*
	ghistwin.cc	GRhino Gnome Frontend History Window
	Copyright (c) 2005, 2006, 2010 Kriang Lerdsuwanakij
	email:		lerdsuwa@users.sourceforge.net

	This program is free software; you can redistribute it and/or modify
	it under the terms of the GNU General Public License as published by
	the Free Software Foundation; either version 2 of the License, or
	(at your option) any later version.

	This program is distributed in the hope that it will be useful,
	but WITHOUT ANY WARRANTY; without even the implied warranty of
	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
	GNU General Public License for more details.

	You should have received a copy of the GNU General Public License
	along with this program; if not, write to the Free Software
	Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/

/*
#define GNOME_DISABLE_DEPRECATED
#define GTK_DISABLE_DEPRECATED
*/

#include "config.h"

#include <gtk/gtk.h>
#include <gnome.h>

#include "board.h"
#include "game.h"
#include "gutil.h"

const
#include "icon_empty.xpm"
const
#include "icon_black.xpm"
const
#include "icon_white.xpm"

/*************************************************************************
	Tools menu - Game history
*************************************************************************/

int gamehist_width, gamehist_height, gamehist_x, gamehist_y;

GtkWidget *tree_view_history;
GtkListStore *list_store_history;
int list_store_size;

extern GnomeUIInfo menu_tools_info[];

void game_history_fill()
{
	static gchar m[NUM_MOVE][3];	// Enough space for A1 .. H8 and string
				// termination
	static gchar p[NUM_MOVE][3];
	static const gchar *pos_table_x = "ABCDEFGH";
	static const gchar *pos_table_y = "12345678";
	static GdkPixbuf *color_table[3];
	static GdkPixbuf *empty_player_pixbuf;   
	static GdkPixbuf *black_player_pixbuf;
	static GdkPixbuf *white_player_pixbuf;

	static bool init = false;
	if (!init) {
		for (int i = 0; i < NUM_MOVE; ++i) {
				// String termination
			m[i][2] = '\0';
			if (i+1 < 10)
				p[i][0] = ' ';
			else
				p[i][0] = (i+1)/10+'0';
			p[i][1] = (i+1)%10+'0';
			p[i][2] = '\0';
		}

		int player_size = 12;
		empty_player_pixbuf = scale_pixbuf_from_xpm_data(const_cast<const char**>(icon_empty_xpm),
								 player_size, player_size);
		black_player_pixbuf = scale_pixbuf_from_xpm_data(const_cast<const char**>(icon_black_xpm),
								 player_size, player_size);
		white_player_pixbuf = scale_pixbuf_from_xpm_data(const_cast<const char**>(icon_white_xpm),
								 player_size, player_size);

		color_table[0] = white_player_pixbuf;
		color_table[2] = black_player_pixbuf;

		init = true;
	}

	GtkTreeIter iter;

	if (list_store_size == 0) {
		gtk_list_store_append(list_store_history, &iter);
		gtk_list_store_set(list_store_history, &iter, 
				   0, 0, 
				   1, "    ", 
				   2, empty_player_pixbuf, 
				   3, _("Begin"), -1);
		++list_store_size;
	}

	if (list_store_size < cur_game_info.num_history)
		for (int i = list_store_size; i < cur_game_info.num_history; ++i) {
			int pos = cur_game_info.move_history[i-1];
			m[i-1][0] = pos_table_x[pos_to_x(pos)];
			m[i-1][1] = pos_table_y[pos_to_y(pos)];
						// WHITE (-1) => 0
						// BLACK (1) => 2
			GdkPixbuf *c = color_table[cur_game_info.player_history[i-1]+1];

			gtk_list_store_append(list_store_history, &iter);
			gtk_list_store_set(list_store_history, &iter, 
					   0, i, 
					   1, p[i-1], 
					   2, c, 
					   3, m[i-1], -1);
			++list_store_size;
		}
	else if (list_store_size > cur_game_info.num_history) {
		GtkTreePath *path = gtk_tree_path_new();
		gtk_tree_path_append_index(path, cur_game_info.num_history);
		gtk_tree_model_get_iter(GTK_TREE_MODEL(list_store_history), 
					&iter, path);
		gtk_tree_path_free(path);
		while (list_store_size > cur_game_info.num_history) {
			gtk_list_store_remove(list_store_history, &iter);
			--list_store_size;
		}
	}
}

void game_history_update(update_state_type u, void *)
{
	switch (u) {
		case UPDATE_NONE:
			break;		// Just update selection
		case UPDATE_BACKWARD:
		case UPDATE_FORWARD:
			game_history_fill();
			break;
		case UPDATE_ALL:
			gtk_list_store_clear(list_store_history);
			list_store_size = 0;
			game_history_fill();
			break;
	}

	GtkTreePath *path = gtk_tree_path_new();
	if (view_mode == VIEW_MODE_HISTORY)
		gtk_tree_path_append_index(path, view_position);
	else
		gtk_tree_path_append_index(path, cur_game_info.num_history-1);

	GtkTreeSelection *selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(tree_view_history));
	gtk_tree_selection_select_path(selection, path);
	gtk_tree_view_scroll_to_cell(GTK_TREE_VIEW(tree_view_history), path, 
				     NULL, FALSE, 0, 0);
	gtk_tree_view_set_cursor(GTK_TREE_VIEW(tree_view_history), path, 
				 NULL, FALSE);
	gtk_tree_path_free(path);
// Scroll problem when scrollbar appears
}

gint game_history_configure_event(GtkWidget *widget, 
				  GdkEventConfigure *e, gpointer /*data*/)
{
	gtk_window_get_position(GTK_WINDOW(widget), &gamehist_x, &gamehist_y);
	gamehist_width = e->width;
	gamehist_height = e->height;
	return FALSE;		// Propagate signal to child so that it
				// can resize itself
}

void game_history_closed(GtkWidget *widget, GtkWidget **data)
{
	update_move.remove(game_history_update, 0);
	gtk_widget_destroy(widget);
	*data = NULL;
	show_game_history = false;
	gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM (menu_tools_info[3].widget),
				       show_game_history);
}

void game_history_selected(GtkTreeSelection *selection, gpointer /*data*/)
{
	GtkTreeIter iter;
	GtkTreeModel *model;
	if (gtk_tree_selection_get_selected(selection, &model, &iter)) {
		int pos;
		gtk_tree_model_get(model, &iter, 0, &pos, -1);
		if (pos != cur_game_info.num_history-1) {
			set_view_mode(VIEW_MODE_HISTORY);
			view_position = pos;
			view_player = cur_game_info.player_history[view_position];
			*view_board_ptr = cur_game_info.board_history[view_position];
			draw_board();
			update_move.update(UPDATE_NONE);
		}
		else if (view_mode == VIEW_MODE_HISTORY) { // pos == cur_game_info.num_history-1
			set_view_mode(VIEW_MODE_NONE);
			*view_board_ptr = *cur_game_info.board_ptr;
			draw_board();
			update_move.update(UPDATE_NONE);
		}
	}
}

void game_history()
{
	static GtkWidget *gamehist = NULL;
	if (gamehist) {
		if (show_game_history)
			gtk_window_present(GTK_WINDOW(gamehist));
		else
			game_history_closed(gamehist, &gamehist);
		return;
	}

	if (!show_game_history)
		return;

	gamehist = gtk_window_new(GTK_WINDOW_TOPLEVEL);
	gtk_window_set_title(GTK_WINDOW(gamehist), _("Game History"));
	gtk_container_set_border_width(GTK_CONTAINER(gamehist), 5);
	g_signal_connect(G_OBJECT(gamehist), "destroy",
			 G_CALLBACK(game_history_closed), &gamehist);
	g_signal_connect(G_OBJECT(gamehist), "configure_event",
			 G_CALLBACK(game_history_configure_event), NULL);

				// Reuse old list_store_history
	if (list_store_history) {
		gtk_list_store_clear(list_store_history);
	}
	else {
		list_store_history = gtk_list_store_new(
						4, G_TYPE_INT, G_TYPE_STRING,
						G_TYPE_OBJECT, G_TYPE_STRING);
	}
	list_store_size = 0;

	GtkWidget *scroll = gtk_scrolled_window_new(NULL, NULL);
	gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(scroll),
				       GTK_POLICY_NEVER,
				       GTK_POLICY_AUTOMATIC);
	if (gamehist_x != -1 && gamehist_y != -1)
		gtk_window_move(GTK_WINDOW(gamehist), gamehist_x, gamehist_y);
	gtk_window_set_default_size(GTK_WINDOW(gamehist), gamehist_width, gamehist_height);
	gtk_scrolled_window_set_shadow_type(GTK_SCROLLED_WINDOW(scroll),
					    GTK_SHADOW_ETCHED_IN);
	gtk_container_add(GTK_CONTAINER(gamehist), scroll);

	tree_view_history = gtk_tree_view_new_with_model(GTK_TREE_MODEL(list_store_history));
	GtkCellRenderer *renderer = gtk_cell_renderer_text_new();
	g_object_set(G_OBJECT(renderer), "xalign", 1.0, NULL);	// Right aligned
	GtkTreeViewColumn *column = gtk_tree_view_column_new_with_attributes(
						"Number",
						renderer,
						"text", 1,
						NULL);
	gtk_tree_view_append_column(GTK_TREE_VIEW(tree_view_history),
				    column);
	column = gtk_tree_view_column_new_with_attributes(
						"Color",
						gtk_cell_renderer_pixbuf_new(),
						"pixbuf", 2,
						NULL);
	gtk_tree_view_append_column(GTK_TREE_VIEW(tree_view_history),
				    column);
	column = gtk_tree_view_column_new_with_attributes(
						"Move",
						gtk_cell_renderer_text_new(),
						"text", 3,
						NULL);
	gtk_tree_view_append_column(GTK_TREE_VIEW(tree_view_history),
				    column);

	gtk_tree_view_set_headers_visible(GTK_TREE_VIEW(tree_view_history),
					  FALSE);
				// This may cause lots of flicker
	gtk_tree_view_set_rules_hint(GTK_TREE_VIEW(tree_view_history), TRUE);

	GtkTreeSelection *selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(tree_view_history));
	gtk_tree_selection_set_mode (selection, GTK_SELECTION_SINGLE);

	gtk_container_add(GTK_CONTAINER(scroll), tree_view_history);

	game_history_fill();
	update_move.add(game_history_update, 0);

	gtk_widget_show_all(gamehist);
	game_history_update(UPDATE_NONE, 0);	// Highlight current view

						// Start tracking user selection
	g_signal_connect(G_OBJECT(selection), "changed",
			 G_CALLBACK(game_history_selected), NULL);
}

